/* EVENTS4.C */

#include <p_std.h>
#include <p_file.h>
#include <p_cons.h>
#include <epoc.h>
#include <wskeys.h>
#include "subproc.h"


GLREF_C TEXT *DatCommandPtr;

LOCAL_D VOID *timH;
LOCAL_D WORD timstat;
LOCAL_D WORD counter;
LOCAL_D ULONG timint;

LOCAL_D VOID *conH;
LOCAL_D WORD keystat;
LOCAL_D P_CON_KBREC key;

LOCAL_D WORD subexist;
LOCAL_D WORD substat;
LOCAL_D WORD answer;

LOCAL_D VOID *serH;
LOCAL_D WORD serstat;
LOCAL_D WORD serlen;
LOCAL_D TEXT serbuf[2];
LOCAL_D WORD serpos;

LOCAL_D WORD thinkcount;
LOCAL_D TEXT thinkchar[4]={'-','\\','|','/'};

#define MAX_COUNT   100
#define MAX_SERPOS   11
#define MAX_THINK    20


LOCAL_C VOID QueueKey(VOID)
    {
    p_ioa4(conH,P_FREAD,&keystat,&key);
    }

LOCAL_C VOID QueueTimer(VOID)
    {
    p_ioa4(timH,P_FRELATIVE,&timstat,&timint);
    }

LOCAL_C VOID CancelTimer(VOID)
    {
    p_iow2(timH,P_FCANCEL);
    p_waitstat(&timstat);
    }

LOCAL_C VOID Check(INT val,TEXT *msg)
    {
    TEXT buf[30];

    if (!val)
        return;
    p_atos(&buf[0],"Failed to open %s",msg);
    p_notifyerr(val,&buf[0],0,0,0);
    p_exit(0);
    }

LOCAL_C VOID OpenTimer(VOID)
    {
    Check(p_open(&timH,"TIM:",-1),"timer");
    }

LOCAL_C VOID OpenConsole(VOID)
    {
    P_RECT rect;
    WORD func;

    Check(p_open(&conH,"CON:",-1),"console");
    rect.tl.x=rect.tl.y=0;
    rect.br.x=25;
    rect.br.y=9;
    func=P_SCR_WSET;
    Check(p_iow4(conH,P_FSET,&func,&rect),"console");
    }

LOCAL_C VOID SetTimInt(INT new)
    {
    CancelTimer();
    timint=new;
    QueueTimer();
    }

LOCAL_C VOID Write(INT x,INT y,TEXT *pb,INT len)
    {
    P_POINT pos;
    WORD func;

    pos.x=x;
    pos.y=y;
    func=P_SCR_POSA;
    p_iow4(conH,P_FSET,&func,&pos);
    p_write(conH,pb,len);
    }

LOCAL_C VOID DisplayCount(VOID)
    {
    TEXT buf[4];

    p_atos(&buf[0],"%3d",counter);
    Write(10,2,&buf[0],3);
    }

LOCAL_C VOID DrawBorder(VOID)
    {
    TEXT buf[26];
    INT i;

    p_bfil(&buf[0],26,'*');
    Write(0,0,&buf[0],25);
    for (i=1; i<8; i++)
        {
        Write(0,i,&buf[0],1);
        Write(24,i,&buf[0],1);
        }
    Write(0,8,&buf[0],25);
    }

LOCAL_C VOID Message(TEXT *pb)
    {
    TEXT buf[22];
    INT len;

    p_bfil(&buf[0],22,' ');
    len=p_slen(pb);
    p_bcpy(&buf[10-len/2],pb,len);
    Write(2,6,&buf[0],21);
    }

LOCAL_C VOID LaunchSub(VOID)
    {
    HANDLE pid;
    SUBPROC_CL cl;
    TEXT subname[P_FNAMESIZE];

    if (subexist)
        {
        p_sound(-5,320);
        return;
        }
    p_fparse("subproc.img",DatCommandPtr,&subname[0],0);
    cl.pid=p_getpid();
    cl.poff=(&answer);
    cl.data=p_date();
    if ((pid=p_execc(&subname[0],&cl,sizeof(cl)))<0)
        {
        p_notifyerr(pid,"Failed to launch subprocess",0,0,0);
        return;
        }
    p_logona(pid,&substat);
    subexist=TRUE;
    Message("Subp launched");
    p_presume(pid);
    }

LOCAL_C VOID ReportSub(VOID)
    {
    TEXT buf[22];

    subexist=FALSE;
    if (substat)
        Message("Subp abnormal exit");
    else
        {
        p_atos(&buf[0],"Subp slept %d ticks",answer);
        Message(&buf[0]);
        }
    }

LOCAL_C VOID QueueSer()
    {
    if (!serH)
        return;
    serlen=1;
    p_ioa5(serH,P_FREAD,&serstat,&serbuf[0],&serlen);
    }

LOCAL_C VOID OpenSer()
    {
    INT ret;

    ret=p_open(&serH,"TTY:B",-1);
    if (ret<0)
        ret=p_open(&serH,"TTY:A",-1);
    if (ret<0)
        {
        p_notifyerr(ret,"Opening serial port",0,0,0);
        serH=0;
        }
    }

LOCAL_C VOID DisplaySerChar(VOID)
    {
    TEXT buf[12];

    if (!serlen || !p_isprint(serbuf[0]))
        return;
    if (serpos++==MAX_SERPOS)
        {
        serpos=1;
        p_bfil(&buf[0],12,' ');
        Write(7,4,&buf[0],11);
        }
    Write(6+serpos,4,&serbuf[0],1);
    }

LOCAL_C VOID Think(VOID)
    {
    TEXT *pb;

    if (thinkcount++==MAX_THINK)
        thinkcount=0;
    pb=(&thinkchar[thinkcount/5]);
    Write(0,4,pb,1);
    Write(25,4,pb,1);
    }

LOCAL_C VOID QueueThink(VOID)
    {
    p_iosignal();
    }

GLDEF_C VOID main(VOID)
    {
    p_unmarka();
    OpenConsole();
    DrawBorder();
    OpenTimer();
    timint=10;
    QueueTimer();
    QueueKey();
    LaunchSub();
    OpenSer();
    QueueSer();
    QueueThink();
    FOREVER
        {
        p_iowait();
        if (keystat!=E_FILE_PENDING)
            {
            if (key.keycode==W_KEY_ESCAPE)
                p_exit(0);
            if (key.keycode==W_KEY_RETURN)
                LaunchSub();
            else if (key.keycode>='1' && key.keycode<='9')
                SetTimInt(2*(key.keycode-'0'));
            QueueKey();
            }
        else if (timstat!=E_FILE_PENDING)
            {
            if (counter++==MAX_COUNT)
                counter=1;
            DisplayCount();
            QueueTimer();
            }
        else if (subexist && substat!=E_FILE_PENDING)
            ReportSub();
        else if (serH && serstat!=E_FILE_PENDING)
            {
            p_tickle();
            DisplaySerChar();
            QueueSer();
            }
        else
            {
            Think();
            QueueThink();
            }
        }
    }
